Floyd-Warshall Algorithm
The Floyd-Warshall Algorithm is a dynamic programming method used to find the shortest paths between all pairs of nodes in a weighted graph. This algorithm can handle both directed and undirected graphs and works with graphs that have negative weight edges, though it cannot handle graphs with negative weight cycles.
Properties
- Algorithm Type: Dynamic Programming
- Graph Type: Weighted graph (both directed and undirected)
- Edge Weights: Positive or negative (but no negative weight cycles)
- Complexity: , where is the number of vertices
Algorithm Workflow
The algorithm uses a dynamic programming approach to iteratively improve the estimate of the shortest path between all pairs of vertices. It operates on a matrix where the value at the row and column represents the shortest path from vertex to vertex . Initially, this matrix is filled with the direct distances between vertices, which is the weight of the edge connecting them, or infinity if no direct edge exists.
The core of the algorithm involves three nested loops, each running through all vertices. For each pair of vertices and , the algorithm considers whether a vertex can act as an intermediate point on a shorter path between and than any previously known paths. The decision is based on the equation:
This step is repeated for each vertex , effectively testing every vertex as an intermediate point in paths between all pairs of vertices.
-
Initialize:
- Create a 2D array
distto store the shortest path distances. - Set
dist[i][j]to the weight of the edge between vertexiand vertexjif such an edge exists. Otherwise, set it to infinity (or a very large value). - Set
dist[i][i] = 0for alli(self-loops have zero cost).
- Create a 2D array
-
Iterate:
- Use each vertex
kas an intermediate vertex and update the distances for all pairs(i, j): - If
dist[i][j] > dist[i][k] + dist[k][j], updatedist[i][j]todist[i][k] + dist[k][j].
- Use each vertex
-
Detect Negative Cycles:
- After the above steps, if any diagonal value
dist[i][i]is negative, then the graph contains a negative weight cycle.
- After the above steps, if any diagonal value
Complexity
Time Complexity
The time complexity of the Floyd-Warshall algorithm is , where is the number of vertices in the graph. This complexity arises because the algorithm requires three nested loops over the vertices. Despite this seemingly high complexity, the algorithm is efficient in practice for dense graphs due to its straightforward implementation and the constant time required for each update operation.
Space Complexity
The space complexity of the Floyd-Warshall algorithm is because it maintains a matrix that stores the shortest path distances between all pairs of vertices.
Pseudocode
The algorithm initializes a matrix of distances with being the weight of the edge or if there is no direct edge between the vertices. If , . The core of the algorithm then updates the matrix to include the shortest possible paths between each pair of nodes through an intermediate vertex.
function FloydWarshall(W, n)
D := W // Start with the weight matrix
for k from 1 to n
for i from 1 to n
for j from 1 to n
if D[i][k] + D[k][j] < D[i][j]
D[i][j] = D[i][k] + D[k][j]
return D
Parameters:
- : The initial matrix of edge weights between vertices.
- : The number of vertices in the graph.
Example in Python
Here’s a practical implementation of the Floyd-Warshall algorithm in Python:
def floyd_warshall(weights, num_vertices):
# Create a distance matrix from weight matrix
dist = list(map(lambda i: list(map(lambda j: j, i)), weights))
# Apply Floyd-Warshall Algorithm
for k in range(num_vertices):
for i in range(num_vertices):
for j in range(num_vertices):
# Update the distance matrix with the shorter path found
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
# Example graph represented as an adjacency matrix
inf = float('inf')
graph = [
[0, 3, inf, inf],
[2, 0, inf, inf],
[inf, 7, 0, 1],
[6, inf, inf, 0]
]
# Running the algorithm
shortest_paths = floyd_warshall(graph, 4)
for row in shortest_paths:
print(row)
This example utilizes a matrix where each row and column represent a vertex in the graph, and the values represent the weights of the edges or if no direct edge exists. The output will display the shortest paths between all pairs of vertices.